import { Injectable, Inject, Scope } from "@nestjs/common";
import { WINSTON_MODULE_PROVIDER } from "nest-winston";
import { Logger } from "winston";
import { LogsService } from "./logs.service";
import { LogLevel, LogType } from "./logs.entity";
import chalk from "chalk";

/**
 * 简化的统一日志服务
 *
 * 整合了Winston日志、错误格式化和数据库存储功能
 * 提供简洁的API和智能的输出控制
 */
@Injectable({ scope: Scope.REQUEST })
export class SimpleLoggerService {
  constructor(
    @Inject(WINSTON_MODULE_PROVIDER)
    private readonly logger: Logger,
    private readonly logsService: LogsService,
  ) {}

  /**
   * 记录信息日志
   */
  info(message: string, context?: string, meta?: Record<string, unknown>) {
    this.logger.info(message, { context, ...meta });
    this.saveToDatabase(message, LogLevel.INFO, context, meta);
  }

  /**
   * 记录警告日志
   */
  warn(message: string, context?: string, meta?: Record<string, unknown>) {
    this.logger.warn(message, { context, ...meta });
    this.saveToDatabase(message, LogLevel.WARN, context, meta);
  }

  /**
   * 记录错误日志 - 增强格式化输出
   */
  error(message: string | Error, context?: string, meta?: Record<string, unknown>) {
    let errorMessage: string;
    let errorStack: string | undefined;

    if (message instanceof Error) {
      errorMessage = message.message;
      errorStack = message.stack;
    } else {
      errorMessage = message;
    }

    // 格式化错误输出到控制台
    this.logFormattedError(errorMessage, errorStack, context, meta);

    // 保存到数据库
    if (message instanceof Error) {
      this.logsService.createErrorLog(message, context, undefined, meta).catch(this.handleDbError);
    } else {
      this.saveToDatabase(errorMessage, LogLevel.ERROR, context, meta);
    }
  }

  /**
   * 记录HTTP异常 - 专门用于异常过滤器
   */
  logHttpException(exception: unknown, request: any, status: number, context: string = "HttpException") {
    const requestId = this.generateRequestId();
    const method = request.method;
    const url = request.url;
    const userAgent = request.get?.("User-Agent") || "Unknown";
    const ip = request.ip || request.connection?.remoteAddress || "Unknown";

    let message: string;
    let errorDetails: any = {};

    if (exception instanceof Error) {
      message = exception.message;
      errorDetails = {
        name: exception.name,
        stack: exception.stack,
      };
    } else {
      message = String(exception);
    }

    // 根据状态码决定日志级别和输出详细程度
    if (status >= 500) {
      // 服务器错误 - 详细输出
      console.log(chalk.red.bold(`\n🚨 服务器错误 [${status}]`));
      console.log(chalk.red(`📍 ${method} ${url}`));
      console.log(chalk.red(`💬 ${message}`));
      console.log(chalk.gray(`🆔 RequestID: ${requestId}`));
      console.log(chalk.gray(`🌐 IP: ${ip}`));

      if (errorDetails.stack) {
        console.log(chalk.red(`📚 堆栈信息:`));
        console.log(chalk.gray(errorDetails.stack));
      }
      console.log(chalk.red(`${"=".repeat(60)}\n`));

      this.saveToDatabase(`${method} ${url} - ${message}`, LogLevel.ERROR, context, {
        status,
        requestId,
        ip,
        userAgent,
        errorDetails,
      });
    } else if (status >= 400) {
      // 客户端错误 - 简化输出
      console.log(chalk.yellow(`⚠️  客户端错误 [${status}]: ${message} | ${method} ${url} | ID: ${requestId}`));

      this.saveToDatabase(`${method} ${url} - ${message}`, LogLevel.WARN, context, {
        status,
        requestId,
        ip,
        userAgent,
      });
    } else {
      // 其他情况 - 最简输出
      if (process.env.NODE_ENV === "development") {
        console.log(chalk.blue(`ℹ️  HTTP异常 [${status}]: ${message} | ${method} ${url}`));
      }
    }

    return requestId;
  }

  /**
   * 记录用户操作 - 仅重要操作输出到控制台
   */
  async logUserAction(
    userId: number,
    action: string,
    resource: string,
    details?: Record<string, unknown>,
    result: number = 0,
  ) {
    const message = `用户 ${userId} 执行 ${action} 操作于 ${resource}`;

    // 仅重要操作输出到控制台
    const importantActions = ["login", "logout", "delete", "create"];
    if (importantActions.some((keyword) => action.toLowerCase().includes(keyword))) {
      console.log(chalk.cyan(`👤 ${message}`));
    }

    try {
      await this.logsService.createLog({
        level: LogLevel.INFO,
        logType: LogType.AUTH,
        message,
        context: "UserAction",
        userId,
        meta: { action, resource, details },
        result,
      });
    } catch (error) {
      this.handleDbError(error);
    }
  }

  /**
   * 记录数据库操作 - 仅危险操作输出到控制台
   */
  async logDatabaseOperation(operation: string, table: string, details?: Record<string, unknown>, userId?: number) {
    const message = `数据库操作: ${operation} on ${table}`;

    // 仅危险操作输出到控制台
    const dangerousOps = ["DELETE", "DROP", "TRUNCATE", "ALTER"];
    if (dangerousOps.some((op) => operation.toUpperCase().includes(op))) {
      console.log(chalk.red(`🗃️  ${message}`));
    }

    try {
      await this.logsService.createLog({
        level: LogLevel.INFO,
        logType: LogType.DATABASE,
        message,
        context: "Database",
        userId,
        meta: { operation, table, details },
        result: 0,
      });
    } catch (error) {
      this.handleDbError(error);
    }
  }

  /**
   * 调试日志 - 仅开发环境
   */
  debug(message: string, context?: string, meta?: Record<string, unknown>) {
    if (process.env.NODE_ENV === "development") {
      console.log(chalk.gray(`🔍 [${context || "Debug"}] ${message}`));
    }
    this.saveToDatabase(message, LogLevel.DEBUG, context, meta);
  }

  /**
   * 格式化错误输出到控制台
   */
  private logFormattedError(message: string, stack?: string, context?: string, meta?: Record<string, unknown>) {
    console.log(chalk.red.bold(`\n❌ 错误 [${context || "Unknown"}]`));
    console.log(chalk.red(`💬 ${message}`));

    if (meta && Object.keys(meta).length > 0) {
      console.log(chalk.gray(`📋 详情: ${JSON.stringify(meta, null, 2)}`));
    }

    if (stack && process.env.NODE_ENV === "development") {
      console.log(chalk.gray(`📚 堆栈:`));
      console.log(chalk.gray(stack));
    }

    console.log(chalk.red(`${"=".repeat(50)}\n`));
  }

  /**
   * 保存日志到数据库
   */
  private saveToDatabase(message: string, level: LogLevel, context?: string, meta?: Record<string, unknown>) {
    this.logsService.createSystemLog(message, level, context, meta).catch(this.handleDbError);
  }

  /**
   * 处理数据库保存错误
   */
  private handleDbError = (error: any) => {
    console.error(chalk.red(`💾 数据库日志保存失败: ${error.message}`));
  };

  /**
   * 生成请求ID
   */
  private generateRequestId(): string {
    return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * 获取原始Winston Logger实例（兼容性）
   */
  getWinstonLogger(): Logger {
    return this.logger;
  }
}
